﻿using System;

namespace Centido.Core
{
    /// <summary>
    ///   A set of table column read all operations.
    /// </summary>
    public static class ColumnReadAllOperations
    {
        /// <summary>
        ///   Reads the data in the column in all rows in the specified data source.
        /// </summary>
        /// <param name="column">The target table column. </param>
        /// <param name="dataSource">The target data source.</param>
        /// <param name="readAction">The read action to be performed upon each row.</param>
        private static void ReadAllImplementation(Column column,
            DataSource dataSource, Action<ColumnValue> readAction)
        {
            var tableName = column.GetDataSourceName(dataSource);

            var resultValue = column.EmptyValue();

            column.Domain.DbAccess.ExecuteReader(
                cmd =>
                {
                    cmd.CommandText = string.Format(
                        "select {0} from {1}",
                        column.Name,
                        tableName);
                },
                reader =>
                {
                    resultValue.Value = reader[0];

                    if (readAction != null) readAction(resultValue);
                });
        }


        /// <summary>
        ///   Reads data in the column in all rows.
        /// </summary>
        /// <remarks>
        /// The current user has to have the select permission on the table in order to execute this function.
        /// </remarks>
        /// <param name="column">The target table column.</param>
        /// <param name="readAction">The read action to performed upon each row.</param>
        /// <exception cref="System.Data.Common.DbException">Thrown when the current user has no permission to execute this function.</exception>
        /// <example>
        ///   The following example shows how to read data in the column in all rows.
        /// <code>
        ///     using System;
        ///     using Centido.Core;
        /// 
        ///     class Sample
        ///     {
        ///         static void Main()
        ///         {
        ///             var domainConfig = new DomainConfiguration()
        ///             {
        ///                 DbConnectionString = @"Driver={SQL Server};Server=.\SQLEXPRESS;Database=MyDb;Uid=admin;Pwd=P@ssw0rd;",
        ///                 DbProviderName = "MSSQLSERVER"
        ///             };
        ///         
        ///             var domain = Domain.Build(domainConfig);
        ///         
        ///             domain.DeleteAll();
        ///             
        ///             //Adding a new table
        ///             var table = domain.AddTable("students");
        /// 
        ///             //Adding a column
        ///             var surnameColumn = table.AddColumn("surname", ColumnType.String);
        /// 
        ///             //Granting all necessary permissions
        ///             table.GrantAll();
        /// 
        ///             //Inserting two rows
        ///             table.InsertRow(surnameColumn.Value("Smith"));
        ///             table.InsertRow(surnameColumn.Value("Brown"));
        /// 
        ///             //Reading the column in all rows
        ///             surnameColumn.ReadAll(surname =&gt;
        ///             {
        ///                 Console.WriteLine("Student: surname = {0}", surname.GetString());
        ///             });
        ///         }
        ///     }
        /// </code>
        /// </example>
        public static void ReadAll(this Column column, Action<ColumnValue> readAction)
        {
            if (column == null)
                throw new ArgumentNullException("column");

            ReadAllImplementation(column, DataSource.UserView, readAction);
        }


        /// <summary>
        ///   Reads data in the column in all rows from the specified data source.
        /// </summary>
        /// <remarks>The current user has to have the select permission on the specified data source
        /// on order to execute this function.</remarks>
        /// <param name="column">The target table column.</param>
        /// <param name="dataSource">The target data source.</param>
        /// <param name="readAction">The read action to be performed upon each row.</param>
        /// <exception cref="System.Data.Common.DbException">Thrown when the current user has no permission on the specified data source.</exception>
        /// <example>
        ///   The following example shows how to read data in the column in all rows from the specified data source.
        /// <code>
        ///     using System;
        ///     using Centido.Core;
        /// 
        ///     class Sample
        ///     {
        ///         static void Main()
        ///         {
        ///             var domainConfig = new DomainConfiguration()
        ///             {
        ///                 DbConnectionString = @"Driver={SQL Server};Server=.\SQLEXPRESS;Database=MyDb;Uid=admin;Pwd=P@ssw0rd;",
        ///                 DbProviderName = "MSSQLSERVER"
        ///             };
        ///         
        ///             var domain = Domain.Build(domainConfig);
        ///         
        ///             domain.DeleteAll();
        ///             
        ///             //Adding a new table
        ///             var table = domain.AddTable("students");
        /// 
        ///             //Adding a column
        ///             var surnameColumn = table.AddColumn("surname", ColumnType.String);
        /// 
        ///             //Granting all necessary permissions
        ///             table.GrantAll();
        /// 
        ///             //Inserting two rows
        ///             table.InsertRow(surnameColumn.Value("Smith"));
        ///             table.InsertRow(surnameColumn.Value("Brown"));
        /// 
        ///             //Reading the column in all rows
        ///             surnameColumn.ReadAll(DataSource.UserView, surname =&gt;
        ///             {
        ///                 Console.WriteLine("Student: surname = {0}", surname.GetString());
        ///             });
        ///         }
        ///     }
        /// </code>
        /// </example>
        public static void ReadAll(this Column column,
            DataSource dataSource, Action<ColumnValue> readAction)
        {
            if (column == null)
                throw new ArgumentNullException("column");

            ReadAllImplementation(column, dataSource, readAction);
        }
    }
}
